package luzhin;

import java.util.*;
import java.io.*;

import static luzhin.Piece.*;

/**
 * Class creating attack diagrams.
 * Used for tests.
 * @author lacungus
 *
 */
public class AdvancedAttackDiagramBuilder implements AttackDiagramBuilder, Serializable {

	private final static long serialVersionUID = 54254523L;
	public AdvancedAttackDiagramBuilder() {
	}

	private int[] whiteAttacks;
	private int[] blackAttacks;
    private byte[] field;

	// calculate attacks from the pos.
	private void processPosition(int pos) {
		int piece = field[pos];
		if (piece == Piece.NONE)
			return;

        int[] dx = {};
		int[] dy = {};
		int limit = 0;

		if (piece == WQ || piece == BQ) {
			dx = Piece.dxQueen;
			dy = Piece.dyQueen;
			limit = Board.LEN;
		}
		if (piece == WR || piece == BR) {
			dx = Piece.dxRook;
			dy = Piece.dyRook;
			limit = Board.LEN;
		}
		if (piece == WN || piece == BN) {
			dx = Piece.dxKnight;
			dy = Piece.dyKnigth;
			limit = 1;
		}
		if (piece == WB || piece == BB) {
			dx = Piece.dxBishop;
			dy = Piece.dyBishop;
			limit = Board.LEN;
		}
		if (piece == WK || piece == BK) {
			dx = Piece.dxKing;
			dy = Piece.dyKing;
			limit = 1;
		}
		if (piece == WP) {
			dx = Piece.dxWhitePawn;
			dy = Piece.dyWhitePawn;
			limit = 1;
		}
		if (piece == BP) {
			dx = Piece.dxBlackPawn;
			dy = Piece.dyBlackPawn;
			limit = 1;
		}
		int i = pos / Board.LEN;
		int j = pos % Board.LEN;

        int[] attacksToIncrement = (Piece.getColor(piece) == 1) ? whiteAttacks : blackAttacks;
		for (int dir=0;dir<dx.length;++dir) {
    		for (int k=1;k<=limit;++k) {
				int x = i + k * dx[dir];
				int y = j + k * dy[dir];
				int ps = Position.getPosition(x, y);
				if (ps == Position.INVALID) {
                    break;
				}
				attacksToIncrement[ps]++;
				if (field[ps] != Piece.NONE) {
					break;
				}
			}
		}
	}

	/**
	 * Building diagram.
	 * @param board
	 * @return Attack diagram.
	 */
	public AttackDiagram buildAttackDiagram(Board board) {
        this.field = board.getField();
		whiteAttacks = new int[Board.SIZE];
		blackAttacks = new int[Board.SIZE];
		Arrays.fill(whiteAttacks, 0);
		Arrays.fill(blackAttacks, 0);

		for (int i=0;i<Board.SIZE;++i)
			processPosition(i);

		boolean isSafe = true;
		int whiteKingPos = 0;
		int blackKingPos = 0;
		for (int i=0;i<Board.SIZE;++i) {
			int color = Piece.getColor(field[i]);
			if (color == 1 && whiteAttacks[i] < blackAttacks[i]) {
				isSafe = false;
			}
			if (color == -1 && blackAttacks[i] < whiteAttacks[i]) {
				isSafe = false;
			}
			if (field[i] == Piece.WK)
				whiteKingPos = i;
			if (field[i] == Piece.BK)
				blackKingPos = i;
		}
		boolean checkToWhite = false;
		boolean checkToBlack = false;
		if (blackAttacks[whiteKingPos] > 0)
			checkToWhite = true;
		if (whiteAttacks[blackKingPos] > 0)
			checkToBlack = true;
		AttackDiagram diagram = new AttackDiagram(whiteAttacks, blackAttacks, isSafe, checkToWhite, checkToBlack);
		return diagram;
	}
}
